package com.tobeface.sns.application.security.impl;

import java.util.Map;
import java.util.Random;

import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.velocity.VelocityEngineUtils;

import com.google.common.collect.ImmutableMap;
import com.kissme.lang.Preconditions;
import com.tobeface.sns.application.security.UserService;
import com.tobeface.sns.domain.User;
import com.tobeface.sns.domain.UserNotExistsException;
import com.tobeface.sns.domain.UserRepository;
import com.tobeface.sns.domain.security.Member;
import com.tobeface.sns.infrastructure.mail.EmailService;

/**
 * 
 * @author loudyn
 * 
 */
@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserRepository userRepository;
	private EmailService emailService;
	private VelocityEngine velocityEngine;

	/**
	 * 
	 * @param userRepository
	 * @param emailService
	 * @param velocityEngine
	 */
	@Autowired
	public UserServiceImpl(UserRepository userRepository, EmailService emailService, VelocityEngine velocityEngine) {
		Preconditions.notNull(userRepository);
		Preconditions.notNull(emailService);
		Preconditions.notNull(velocityEngine);

		this.userRepository = userRepository;
		this.emailService = emailService;
		this.velocityEngine = velocityEngine;
	}

	@Override
	public User getByUsername(String username) {
		return userRepository.queryUniqueByUsername(username);
	}

	@Override
	public void updatePassword(String username, String newPassword) {
		userRepository.updatePassword(username, encodePassword(username, newPassword));
	}

	private String encodePassword(String username, String newPassword) {
		Member entity = new Member();
		entity.setUsername(username);
		entity.setPassword(newPassword);
		return entity.encodePassword().getPassword();
	}

	@Override
	public void save(User entity) {
		userRepository.save(entity);
	}

	@Override
	public void forgetPassword(String username, String email) {

		checkUserExists(username, email);
		String newPassword = createNewPassword();

		updatePassword(username, newPassword);
		emailService.send(email, createEmailSubject(username), createEmailContent(username, newPassword));
	}

	private void checkUserExists(String username, String email) {
		if (!existsByUsernameAndEmail(username, email)) {
			throw new UserNotExistsException();
		}
	}

	private String createEmailSubject(String username) {
		return null;
	}

	private String createEmailContent(String username, String newPassword) {
		Map<String, String> model = ImmutableMap.of("username", username, "password", newPassword);
		return VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, "com/sinzv/sns/application/security/impl/forget.vm", model);
	}

	private final static String SEEDS = "abcdefghkmnopqrstwxzABCDEFGHKMNOPQRST23456789";
	private final static Random SEEDS_GENERATOR = new Random();

	private final static int SEED_LENGTH = 8;

	private String createNewPassword() {
		StringBuilder buf = new StringBuilder();
		for (int i = 0; i < SEED_LENGTH; i++) {
			buf.append(SEEDS.toCharArray()[SEEDS_GENERATOR.nextInt(SEEDS.length())]);
		}

		return buf.toString();
	}

	@Override
	public boolean existsByUsernameAndEmail(String username, String email) {
		return userRepository.existsByUsernameAndEmail(username, email);
	}

	@Override
	public boolean existsByUsername(String username) {
		return userRepository.existsByUsernameOrEmail(username);
	}

	@Override
	public User queryUniqueByEmail(String email) {
		return userRepository.queryUniqueByEmail(email);
	}

	@Override
	public void updateEmail(String username, String newEmail) {
		userRepository.updateEmail(username, newEmail);
	}

}
